Add Redis-based token denylist implementation - #1660
Closed
tri-pti wants to merge 1 commit into
Closed
Conversation
Owner
|
@tri-pti Please add a short video demo showcasing your key features for review. |
|
👋 This PR has had no activity for 7 days. Please push updates or comment if you still need more time. Inactive PRs may be closed automatically after 7 more days. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
TokenDenyliststored revoked JWTjtis in a process-localdictguarded by athreading.Lock. In a multi-replica deployment (the example k8s manifest setsreplicas: 2), a token revoked via/logouton one pod was invisible to the others, so it stayed usable on any pod that didn't handle the logout request until it naturally expired.This PR splits the denylist into two interchangeable implementations behind the same
revoke/is_revoked/clearinterface:InMemoryTokenDenylist— the original process-local behavior, used whenREDIS_URLis unset (e.g. single-replica local dev viadocker-compose.yml).RedisTokenDenylist— stores revocations in Redis (SET ... EX/EXISTS), shared by every replica/worker behind the load balancer. Each entry's TTL matches the token's own remaining lifetime, so Redis expires the bookkeeping key for free._build_token_denylist()picks between them at import time based onsettings.redis_url, and falls back to the in-memory store (with a logged warning) if Redis is configured but unreachable at startup — a Redis outage degrades to single-replica-safe behavior instead of crashing the app. The Redis client is constructed with an explicitsocket_connect_timeout/socket_timeout(5s) so that fallback actually happens fast even when the network silently drops packets (common with k8s NetworkPolicies/security group DROP rules) rather than actively refusing the connection.security.py(get_current_user) androuters/auth.py(logout) are unchanged — both call sites only ever depended onis_revoked/revoke, not the storage mechanism.Also updated:
backend/requirements.txt— addedredis>=5.0.0.env.example— documentsREDIS_URLdocker-compose.yml— added an optionalredisservice (opt-in viaREDIS_URL=redis://redis:6379/0; nothing depends on it, so single-replica local dev is unaffected)deploy/k8s/deployment.example.yaml— wiresREDIS_URLfrom aqyverixai-redissecret, since this manifest is the one that actually runsreplicas: 2Related Issue
Closes #1634
Type of change
Labels
GSSoC'26bugChecklist
mainpytest -vand all tests passfeat/fix/docs/test: short descriptionScreenshots (if frontend change)
N/A — backend-only change.
Test evidence